package edu.mtu.citizenscience.cs.notepad.activity;

import java.util.Locale;

import edu.mtu.citizenscience.cs.notepad.NPActivity;
import edu.mtu.citizenscience.cs.notepad.activity.noteslist.note.recording.ProgressDialog;
import edu.mtu.citizenscience.cs.notepad.activity.upload.LoginDialog;
import edu.mtu.citizenscience.cs.sdk.login.CitsciLogin;
import edu.mtu.citizenscience.cs.sdk.login.CitsciLoginCallback;
import edu.mtu.citizenscience.cs.sdk.login.CitsciLoginError;
import edu.mtu.citizenscience.cs.sdk.login.UserLogin;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploader;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderCallback;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderError;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderProgress;
import edu.mtu.citizenscience.cs.utils.Message;

import android.annotation.SuppressLint;
import android.os.Bundle;
/**
 * @author Corbin Uselton <corbinu@cwuselto@mtu.edu>
 * @copyright (c) 2012 MichiganTech <http://www.mtu.edu>
 * @since 1.0
 * 
 * Upload Activity Responsible for 
 * uploading notes to the CitSci server
 */
public class UploadActivity extends NPActivity {
	// citsci interface for logging the user in
	private CitsciLogin citsciLogin;
	// create citsci uploader object for interacting with the uploader service
	private CitsciUploader uploader = new CitsciUploader();
	
	// dialog to display while logging the user in
	private LoginDialog loginDialog = new LoginDialog();
	// create progress dialog to display the current progress of uploads
	private ProgressDialog uploadProgress = new ProgressDialog();
	
	// hold the most recent progress message, max and update for the progress dialog
	private String progressMessage = "";
	private int progressMax = 0;
	private int progressUpdate = 0;

	/**
	 * @since 1.0
	 * 
	 * Callbacks for handling the user login
	 */
	private class HandleLogin implements CitsciLoginCallback {

		/**
		 * Called on successful login
		 * 
		 * @param login - UserLogin - the user's username and password
		 * @return void
		 */
		@Override
		public void loginSuccess(UserLogin login)
		{	
			// dismiss the login dialog as we now have the login
			loginDialog.dismiss();
			
			// update the login display
			updateLoginDisplay();
		}

		/**
		 * Called on login error
		 * 
		 * @param error - CitsciLoginError - enum for specific error
		 * @return void
		 */
		@Override
		public void loginError(CitsciLoginError error) 
		{
			// did not get the login so dismiss the dialog
			loginDialog.dismiss();
			
			// switch over the error types and display the appropriate message to the user
			switch (error)
			{
				case NONE: break;
				case INVALID_RESPONSE:
					Message.showMessage(aq.getContext(), "Error: Invalid Response");
				break;
				case NO_CONNECTION:
					Message.showMessage(aq.getContext(), "Could not connect to sever");
				break;
			}
		}

		/**
		 * Called on error message from the login
		 * 
		 * @param message - String - The error message
		 * @return void
		 */
		@Override
		public void loginErrorMessage(String message) 
		{
			// did not get the login so dismiss the dialog
			loginDialog.dismiss();
			
			// display the error message to the user
			Message.showMessage(aq.getContext(), "Error: " + message);
		}
	}
	
	/**
	 * @since 1.0
	 * 
	 * Call backs for handling status changes from the uploader
	 * Handles errors, progress and completion
	 */
	private CitsciUploaderCallback uploaderCallbacks = new CitsciUploaderCallback()
	{
		/**
		 * Called on progress update from the uploader
		 * 
		 * @param progress - CitsciUploaderProgress - enum for progress status
		 * @param reportNum - int - the number of the current report -1 if none
		 * @param fileNum - int - the number of the current file -1 if none 
		 * @return void
		 */
		public void uploaderProgress(CitsciUploaderProgress progress, int reportNum, int fileNum) 
		{
			// switch over the different progress status and set the progress message
			switch (progress)
			{
				case PROCESSING:
					progressMessage = "Processing notes...";
				break;
				case STARTING:
					progressMessage = "Starting New Upload...";
				break;
				case REPORT:
					progressMessage = "Uploading note number " + reportNum;
				break;
				case FILE:
					progressMessage = "Uploading note " + reportNum + " file " + fileNum;
				break;
				case REPORT_DATA:
					progressMessage = "Uploading note " + reportNum + " data";
				break;
				case COMPLETING:
					progressMessage = "Completing Upload...";
				break;
				case UPLOADED:
					// show a toast of how many reports were uploaded
					Message.showMessage(aq.getContext(), reportNum + " Notes Uploaded");
				break;
			}
			// update the progress dialog with the new status
			updateProgress();
		}
		
		/**
		 * Called on progress max update from the uploader
		 * 
		 * @param max - int - the maximum for the dialogs progress bar
		 * @return void
		 */
		public void uploaderProgressMax(int max) 
		{
			// set the progressbar max
			progressMax = max;
			// update the progress dialog
			updateProgress();
		}
		
		/**
		 * Called on progress update from the uploader
		 * 
		 * @param update - int - the current value for the dialogs progress bar
		 * @return void
		 */
		public void uploaderProgressUpdate(int update) 
		{
			// set the progressbar current value
			progressUpdate = update;
			// update the progress dialog
			updateProgress();
		}

		/**
		 * Called on error from the uploader
		 * 
		 * @param code - CitsciUploaderError - enum for specific error
		 * @return void
		 */
		public void uploaderError(CitsciUploaderError code) 
		{
			// switch over the different error codes and display the appropriate message to the user as a toast
			switch (code)
			{
				case NONE: break;
				case ALREADY_UPLOADING:
					Message.showMessage(aq.getContext(), "Uploader already uploading please wait");
				break;
				case NOT_LOGGED_IN:
					Message.showMessage(aq.getContext(), "Please login before uploading");
				break;
				case NO_CONNECTION:
					Message.showMessage(aq.getContext(), "Could not connect to server");
				break;
				case INVALID_RESPONSE:
					Message.showMessage(aq.getContext(), "Error: Invalid response from server");
				break;
				case NO_ENTRIES:
					Message.showMessage(aq.getContext(), "No new reports to upload");
				break;
			}
			uploadProgress.dismiss();
		}

		/**
		 * Called on error message from the uploader
		 * 
		 * @param message - String - The error message
		 * @return void
		 */
		public void uploaderErrorMessage(String message) 
		{
			// display the error message usually a message from the server
			Message.showMessage(aq.getContext(), "Error: " + message);
		}

		/**
		 * Called when the upload is complete
		 * 
		 * @param void
		 * @return void
		 */
		public void uploaderUploadComplete() 
		{
			// dismiss the upload dialog
			uploadProgress.dismiss();
		}
		
	};
	
	/**
	 * Upload Activity creation handler
	 * 
	 * @param   savedInstanceState - Bundle - Bundle with launch info
	 * @return	void
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		
		this.setContentView(R.layout.activity_upload);
		
		// create new login object
		this.citsciLogin = new CitsciLogin(this.aq);
		
		// set the click handler for the upload button to uploadNotes
		this.aq.id(R.id.uploadButton).clicked(this, "uploadNotes");
        
		// update the login display
        this.updateLoginDisplay();
	}
	
	/**
	 * Upload Activity resume handler
	 * 
	 * @param   void
	 * @return	void
	 */
	@Override
	public void onResume()
	{
		super.onResume();
		
		// resume the uploader service with the uploader callbacks
		this.uploader.resume(this, uploaderCallbacks);
	}
	
	/**
	 * Upload Activity pause handler
	 * 
	 * @param   void
	 * @return	void
	 */
	@Override
	public void onPause()
	{	
		super.onPause();
		
		// check if the upload progress dialog is showing
		if (this.uploadProgress.isAdded())
		{
			// dismiss the upload dialog
			this.uploadProgress.dismiss();
		}
		
		// pause the upload service
		this.uploader.pause(this);
	}
	
	/**
	 * Update the upload progress dialog
	 * 
	 * @param   void
	 * @return	void
	 */
	public void updateProgress()
	{
		// make sure the progress dialog is showing, will do nothing if is already showing
		this.uploadProgress.show(this.getSupportFragmentManager(), "dialog");
		// set the max possible progress for the progress bar
		this.uploadProgress.setMax(this.progressMax);
		// set the current progress for the progress bar
		this.uploadProgress.updateProgress(this.progressUpdate);
		// set the progress dialog progress label
		this.uploadProgress.setProgressLabel(this.progressMessage);
	}
	
	/**
	 * Updates the login display for if the user is logged in or not
	 * 
	 * @param   void
	 * @return	void
	 */
	public void updateLoginDisplay()
	{
		// get the current user login
		 UserLogin login = this.citsciLogin.getLogin();
		
		// check to see if we have the users login
		if (login.haveLogin())
        {
			// set the login logout button text to logout and set the clicked handler as logoutUser
        	this.aq.id(R.id.loginLogoutButton).text(R.string.logout_button_label).clicked(this, "logoutUser");
        	
        	// set the username input the users username and disable it from editing
        	this.aq.id(R.id.userInput).text(login.getUsername()).enabled(false);
        	// fill the password field with fake_pass and disable it from editing
        	this.aq.id(R.id.passwordInput).text("fake_passs").enabled(false);
        }
        else
        {
        	// set the login logout button text to login and set the clicked handler as loginUser
        	this.aq.id(R.id.loginLogoutButton).text(R.string.login_button_label).clicked(this, "loginUser");
        	// clear the user input field and enable it
        	this.aq.id(R.id.userInput).text("").enabled(true);
        	// clear the password input field and enable it
        	this.aq.id(R.id.passwordInput).text("").enabled(true);
        }
	}
	
	/**
	 * onClick handler for the upload button
	 * 
	 * @param   void
	 * @return	void
	 */
	public void uploadNotes()
	{
		// start the uploader for the main table
		this.uploader.startUpload("ORM_MODELNOTE");
	}
	
	/**
	 * onClick handler for the login button
	 * 
	 * @param   void
	 * @return	void
	 */
	@SuppressLint("DefaultLocale")
	public void loginUser()
	{
		// get the username from the user input and set it to lower case
		String username = this.aq.id(R.id.userInput).getText().toString().toLowerCase(Locale.getDefault());
		// get the password from the password input
		String password = this.aq.id(R.id.passwordInput).getText().toString();
		
		// display the login dialog so the user knows the app is working
		this.loginDialog.show(getSupportFragmentManager(), "loginDialog");
		
		// do login of the user with the username, password and handle login callbacks
		this.citsciLogin.doLogin(username, password, new HandleLogin());
	}
	
	/**
	 * onClick handler for the logout button
	 * 
	 * @param   void
	 * @return	void
	 */
	public void logoutUser()
	{
		// clear the stored login
		this.citsciLogin.clearLogin();
		
		// update the login display
		this.updateLoginDisplay();
	}

}